import logging
import os
import platform
import plistlib
import shutil
import sys

from PyInstaller.__main__ import run

from create_icon import create_icon

# 配置日志
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
current_dir = os.path.abspath(os.path.dirname(__file__))


def create_info_plist():
    """创建Info.plist文件，包含必要的权限声明"""
    info_plist = {
        "CFBundleIdentifier": "com.subtitle.app",
        "CFBundleName": "字幕助手",
        "CFBundleDisplayName": "字幕助手",
        "CFBundlePackageType": "APPL",
        "CFBundleSignature": "????",
        "LSMinimumSystemVersion": "10.10.0",
        "NSHighResolutionCapable": True,
        "CFBundleIconFile": "app.icns",
    }

    try:
        plist_path = "Info.plist"
        with open(plist_path, "wb") as f:
            plistlib.dump(info_plist, f)
        logger.info("成功创建 Info.plist 文件")
        return plist_path
    except Exception as e:
        logger.error(f"创建 Info.plist 失败: {str(e)}")
        return None


def post_process_app():
    """处理打包后的应用"""
    try:
        os_type = platform.system().lower()

        if os_type == "darwin":
            app_path = os.path.join("dist", "字幕助手.app", "Contents")
            if not os.path.exists(app_path):
                logger.error("未找到应用包")
                return False

            # 复制Info.plist
            if os.path.exists("Info.plist"):
                shutil.copy("Info.plist", os.path.join(app_path, "Info.plist"))
                os.remove("Info.plist")
                logger.info("成功复制 Info.plist 到应用包")
            # 复制 ffmpeg到应用包
            bin_path = os.path.join(app_path, "MacOS")
            if not os.path.exists(bin_path):
                os.makedirs(bin_path)
            ffmpeg_dest = os.path.join(bin_path, "ffmpeg")
            shutil.copy(os.path.join(current_dir, "bin", "mac", "ffmpeg"), ffmpeg_dest)
            os.chmod(ffmpeg_dest, 0o755)
            logger.info("成功复制 ffmpeg 到应用包")

            bin_path = os.path.join(app_path, "MacOS")
            if not os.path.exists(bin_path):
                os.makedirs(bin_path)

            # 复制Python文件和图标
            resources_path = os.path.join(app_path, "Resources")
            if not os.path.exists(resources_path):
                os.makedirs(resources_path)
            shutil.copy("build/app.icns", os.path.join(resources_path, "app.icns"))
            logger.info("成功复制资源文件到应用包")

        elif os_type == "windows":
            # Windows 下复制必要文件到 dist 目录
            dist_path = os.path.join("dist", "字幕助手")
            if not os.path.exists(dist_path):
                logger.error("未找到应用目录")
                return False

            # 复制Python文件
            logger.info("成功复制资源文件到应用目录")

        return True
    except Exception as e:
        logger.error(f"处理应用包时出错: {str(e)}")
        return False


def build():
    """打包应用程序"""
    if os.path.exists("dist"):
        shutil.rmtree("dist")
    if os.path.exists("build"):
        shutil.rmtree("build")
    try:
        # 获取操作系统类型
        os_type = platform.system().lower()
        logger.info(f"当前操作系统: {os_type}")

        # 创建图标
        if not create_icon():
            return False
        # 创建Info.plist
        if os_type == "darwin":
            if not create_info_plist():
                return False

        # 构建资源文件路径
        copy_files = [
            "res/setting_icon.png",
            "res/file_icon.png",
        ]

        # 获取 whisper 资源文件路径
        import whisper

        whisper_path = os.path.dirname(whisper.__file__)
        whisper_assets = os.path.join(whisper_path, "assets")

        # 获取 whisper 模型文件路径
        model_path = os.path.expanduser("~/.cache/whisper/small.pt")
        if not os.path.exists(model_path):
            logger.info("正在下载 whisper 模型文件...")
            whisper.load_model("small")
            if not os.path.exists(model_path):
                logger.error("下载模型文件失败")
                return False
            logger.info("模型文件下载完成")

        # 创建运行时钩子文件
        runtime_hook = """
import os
import sys
import multiprocessing

def _prevent_new_instance():
    if sys.platform == "darwin" and getattr(sys, "frozen", False):
        os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
        os.environ["MKL_NUM_THREADS"] = "1"
        os.environ["OMP_NUM_THREADS"] = "1"
        os.environ["PYTORCH_START_METHOD"] = "fork"
        os.environ["PYTORCH_MULTIPROCESSING_CONTEXT"] = "fork"
        os.environ["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"] = "YES"
        multiprocessing.set_start_method('fork')

_prevent_new_instance()
"""
        with open("runtime-hook.py", "w") as f:
            f.write(runtime_hook)

        # 基本参数
        params = [
            "main_gui.py",
            "--name=字幕助手",
            "--windowed",
            "--noconfirm",
            "--clean",
            "--onefile",
            "--runtime-hook=runtime-hook.py",
            "--hidden-import=multiprocessing",
            "--hidden-import=multiprocessing.pool",
            "--hidden-import=multiprocessing.managers",
            "--hidden-import=multiprocessing.shared_memory",
            "--hidden-import=multiprocessing.resource_tracker",
            "--hidden-import=multiprocessing.spawn",
            "--hidden-import=multiprocessing.popen_spawn_posix",
            "--hidden-import=multiprocessing.popen_fork",
            "--hidden-import=multiprocessing.forkserver",
            "--hidden-import=multiprocessing.context",
            "--hidden-import=multiprocessing.reduction",
            "--hidden-import=multiprocessing.resource_sharer",
            "--hidden-import=multiprocessing.connection",
            "--hidden-import=multiprocessing.queues",
            "--collect-submodules=torch",
            "--collect-submodules=whisper",
            "--collect-data=whisper",
            "--collect-data=torch",
        ]
        for file in copy_files:
            params.append(f"--add-data={os.path.join(current_dir, file)}:./res")

        # 添加 whisper 资源文件
        params.append(f"--add-data={whisper_assets}:whisper/assets")
        # 添加 whisper 模型文件
        params.append(f"--add-data={model_path}:whisper/models")

        # 根据操作系统添加特定参数
        if os_type == "darwin":
            params.extend(
                [
                    "--icon=build/app.icns",
                    "--target-arch=x86_64",
                    "--osx-bundle-identifier=com.subtitle.app",
                    "--codesign-identity=-",  # 禁用代码签名
                ]
            )
        elif os_type == "windows":
            params.extend(
                [
                    "--icon=build/app.ico",
                ]
            )

        # 运行打包命令
        logger.info("开始打包...")
        run(params)

        # 处理打包后的应用
        if not post_process_app():
            return False

        # 清理临时文件
        if os.path.exists("runtime-hook.py"):
            os.remove("runtime-hook.py")

        logger.info("打包完成")
        return True

    except Exception as e:
        logger.error(f"打包过程出错: {str(e)}")
        return False


if __name__ == "__main__":
    success = build()
    sys.exit(0 if success else 1)
